#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <asm/uaccess.h>
#include <linux/slab.h>
#include <linux/stat.h>
#include <linux/sysfs.h>
#include <uapi/linux/i2c.h>
#include <linux/string.h>
#include <linux/delay.h>
//#include <linux/interrupt.h>
//#include <linux/jiffies.h>
//#include <linux/sched.h>  
//#include <asm/io.h>
//#include <linux/of_gpio.h>
//#include <linux/of_irq.h>
//#include <linux/platform_device.h>
#include "i2c_ap3216c.h"

static struct ap3216c_cdev* ap3216c = NULL;

static int ap3216c_write_reg(struct i2c_client* client, unsigned char addr, 
                                        unsigned char* buf, unsigned char num)
{
    int ret = 0;
    unsigned char val[256] = {0};
    struct i2c_msg msgs = {0};
    val[0] = addr;  // 发送的第一个数据为要访问的寄存器地址
    memcpy(&val[1], buf, num);
#if 1
    msgs.addr = client->addr;  // i2c从设备地址
    msgs.buf = val;            // 要发送数据缓冲区指针
    msgs.len = num + 1;        // 发送的消息数量，包含寄存器地址
    msgs.flags = 0;            // 表示写i2c从设备
    ret = i2c_transfer(client->adapter, &msgs, sizeof(msgs) / sizeof(struct i2c_msg));
    if (ret != sizeof(msgs) / sizeof(struct i2c_msg)) {
        dev_err(&client->dev, "i2c_transfer for write error %d\n", ret);
        ret = -EREMOTEIO;
    } else 
        ret = 0;
#else
    int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
    int i2c_master_send(const struct i2c_client *client, const char *buf, int count)
    int i2c_master_recv(const struct i2c_client *client, char *buf, int count)  

#endif
    return ret;
}

static int ap3216c_read_reg(struct i2c_client* client, unsigned char addr, 
                                        unsigned char* buf, unsigned char num)
{
    int ret = 0;
    struct i2c_msg msgs[2];
#if 1
    msgs[0].addr = client->addr;  // i2c从设备地址
    msgs[0].buf = &addr;          // 读取数据的寄存器地址
    msgs[0].len = 1;              // 寄存器地址长度为1个字节
    msgs[0].flags = 0;            // 发送要读取数据的寄存器地址为读方向

    msgs[1].addr = client->addr;  // i2c从设备地址
    msgs[1].buf = buf;            // 接受数据的缓冲区
    msgs[1].len = num;            // 接收数据长度
    msgs[1].flags = I2C_M_RD;     // 从i2c从设备中读取数据    
    ret = i2c_transfer(client->adapter, msgs, sizeof(msgs) / sizeof(struct i2c_msg));
    if (ret != sizeof(msgs) / sizeof(struct i2c_msg)) {
        dev_err(&client->dev, "i2c_transfer for read error %d\n", ret);
        ret = -EREMOTEIO;
    } else 
        ret = 0;
#else
    int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
    int i2c_master_send(const struct i2c_client *client, const char *buf, int count)
    int i2c_master_recv(const struct i2c_client *client, char *buf, int count)  

#endif
    return ret;
}

static ssize_t ap3216c_read(struct file* filp, char __user* buf, 
                                                size_t size, loff_t* ppos)
{
    int ret = 0, i;
    unsigned short val[3] = {0};
    unsigned char reg_val[6] = {0};
    struct ap3216c_cdev* dev = (struct ap3216c_cdev*)filp->private_data;
    if (size < sizeof(val))
        return -EINVAL;
    for (i = 0; i < 6; i++) {
        ret = ap3216c_read_reg(dev->client, dev->sys_addr.ir_data_low + i, 
                                                    &reg_val[i], 1);
        if (ret < 0)
            return ret;
    }
    // als数据
    val[0] = ((((unsigned short)reg_val[3] << 8) | reg_val[2]) & (0xFFFF));
    // ir_data_low的bit7和ps_data_low的bit6置1时，ir和ps数据无效
    if ((reg_val[0] & 0x80) || (reg_val[4] & 0x40)) {
        val[1] = val[2] = 0;
    } else {
        // ir数据
        val[1] = ((((unsigned short)reg_val[1] << 2) | (reg_val[0] & 0x3)) & (0xFFFF));
        // ps数据
        val[2] = (((((unsigned short)reg_val[5] & 0x3F) << 4) |           \
                        (reg_val[4] & 0x0F)) & (0xFFFF));
    }

    ret = copy_to_user(buf, val, sizeof(val));
    if (ret < 0) {
        dev_err(&dev->client->dev, "copy_to_user error %d\n", ret);
        return -EFAULT;
    }
    return sizeof(val);
}
// 打开设备时要初始化设备
static int ap3216c_open(struct inode* inode, struct file* filp)
{
    unsigned char val;
    struct ap3216c_cdev* dev;
    dev = container_of(inode->i_cdev, struct ap3216c_cdev, cdev); 
	// 如果是非阻塞打开，尝试获取互斥体，获取失败直接返回，获取成功继续执行
	if (filp->f_flags & O_NONBLOCK) {
		// mutex_trylock和down_trylock的返回值意义相反
		if (!mutex_trylock(&dev->mutex))
			return -EBUSY;
	}
	else mutex_lock(&dev->mutex);
    val = AP3216C_RESET;
    // 复位    
    ap3216c_write_reg(dev->client, dev->sys_addr.sys_con, &val, 1);
    // 手册规定复位需要10毫秒，这里等待50毫秒
    mdelay(RESET_DELAY_TIME);

    val = ALS_IR_PS_MODE;
    // 设置成ALS+PS+IR MODE
    ap3216c_write_reg(dev->client, dev->sys_addr.sys_con, &val, 1);

    filp->private_data = dev;
    return 0;
}

static int ap3216c_release(struct inode* inode, struct file* filp)
{
    struct ap3216c_cdev* dev;
    dev = container_of(inode->i_cdev, struct ap3216c_cdev, cdev); 
    mutex_unlock(&dev->mutex);
    return 0;
}

// ap3216c从设备操作函数
static const struct file_operations ap3216c_ops = {
    .owner = THIS_MODULE,
    .open = ap3216c_open,
    .read = ap3216c_read,
    .release = ap3216c_release,
};

static void dumpbuf(char* name, unsigned char* buf, int size)
{
    int i = 0;
    printk("%s\n", name);
    for (i = 0; i < size; i++) {
        printk("%2X ", buf[i]);
        if ((i + 1) % 0xF == 0)
            printk("\n");
    }
    printk("\n");
}

static int ap3216c_get_reg_addr(struct ap3216c_cdev* dev)
{
    int ret = 0;
    ret = of_property_read_u8_array(dev->node, "sys_reg", 
                        (unsigned char*)&(dev->sys_addr), sizeof(struct sys_reg));
    if (ret < 0) {
        dev_err(&dev->client->dev, "read sys_reg property failed %d\n", ret);
        return ret;
    }
    dumpbuf("sys_reg", (unsigned char*)&dev->sys_addr, sizeof(struct sys_reg));

    ret = of_property_read_u8_array(dev->node, "als_reg", 
                        (unsigned char*)&(dev->als_addr), sizeof(struct als_reg));
    if (ret < 0) {
        dev_err(&dev->client->dev, "read als_reg property failed %d\n", ret);
        return ret;
    }
    dumpbuf("als_reg", (unsigned char*)&dev->als_addr, sizeof(struct als_reg));

    ret = of_property_read_u8_array(dev->node, "ps_reg", 
                        (unsigned char*)&(dev->ps_addr), sizeof(struct ps_reg));
    if (ret < 0) {
        dev_err(&dev->client->dev, "read ps_reg property failed %d\n", ret);
        return ret;
    }
    dumpbuf("ps_reg", (unsigned char*)&dev->ps_addr, sizeof(struct ps_reg));
    return ret;
}

static int ap3216c_probe(struct i2c_client* client, const struct i2c_device_id* id)
{
    int ret = 0;
    ap3216c = kzalloc(sizeof(struct ap3216c_cdev), GFP_KERNEL);
    if (NULL == ap3216c) {
        dev_err(&client->dev, "kzalloc failed %d\n", ret);
        return -ENOMEM;
    }
    ap3216c->client = client;
    ap3216c->node = client->dev.of_node;
    ret = alloc_chrdev_region(&ap3216c->devno, 0, CNT, NAME);
    if (ret < 0) {
        dev_err(&client->dev, "alloc_chrdev_region failed %d\n", ret);
        goto free_ap3216c;
    }
    dev_info(&client->dev, "device major numbers %d, minor numbers %d\n",
                MAJOR(ap3216c->devno), MINOR(ap3216c->devno));
    // 初始化字符设备结构体和注册字符设备
    cdev_init(&ap3216c->cdev, &ap3216c_ops);
    ap3216c->cdev.owner = THIS_MODULE;
    ret = cdev_add(&ap3216c->cdev, ap3216c->devno, CNT);
    if (ret < 0) {
        dev_err(&client->dev, "cdev_add failed %d\n", ret);
        goto unregister_devno;        
    }
    // 创建类和设备，便于自动生成设备节点
	ap3216c->ap3216c_class = class_create(THIS_MODULE, NAME);
	if (IS_ERR(ap3216c->ap3216c_class)) {
		ret = PTR_ERR(ap3216c->ap3216c_class);
        dev_err(&client->dev, "class_create failed %d\n", ret);
		goto del_cdev;
	}
	ap3216c->ap3216c_device = device_create(ap3216c->ap3216c_class, 
                        NULL, ap3216c->devno, NULL, NAME);
	if (IS_ERR(ap3216c->ap3216c_device)) {
		ret = PTR_ERR(ap3216c->ap3216c_device);
        dev_err(&client->dev, "device_create failed %d\n", ret);
		goto clean_class;
	}
    // 从设备树中提取ap3216c的寄存器地址信息
    ret = ap3216c_get_reg_addr(ap3216c);
    if (ret < 0) goto clean_device;
    mutex_init(&ap3216c->mutex);
    return 0;

clean_device:
	device_destroy(ap3216c->ap3216c_class, ap3216c->devno);
clean_class: 
	class_destroy(ap3216c->ap3216c_class);
del_cdev:
    cdev_del(&ap3216c->cdev);
unregister_devno:
    unregister_chrdev_region(ap3216c->devno, CNT);
free_ap3216c:
    kfree(ap3216c);
    ap3216c = NULL;
    return ret;
}

static int ap3216c_remove(struct i2c_client* client)
{
	device_destroy(ap3216c->ap3216c_class, ap3216c->devno);
	class_destroy(ap3216c->ap3216c_class);
    cdev_del(&ap3216c->cdev);
    unregister_chrdev_region(ap3216c->devno, CNT);
    kfree(ap3216c);
    ap3216c = NULL;
    return 0;
}

static const struct i2c_device_id ap3216c_id[] = {
    {"my,ap3216c", 0},
    { }
};

// 设备树匹配列表
static const struct of_device_id ap3216c_of_math[] = {
    {.compatible = "my,ap3216c"},
    { }  // 最后一项必须为空
};

static struct i2c_driver ap3216c_driver = {
    .probe = ap3216c_probe,
    .remove = ap3216c_remove,
    .driver = {
        .owner = THIS_MODULE,
        .name = "my, ap3216c",
        .of_match_table = ap3216c_of_math,
    },
    .id_table = ap3216c_id,
};

static int __init ap3216c_init(void)
{
    int ret = i2c_add_driver(&ap3216c_driver);
    if (ret != 0) {
        pr_err("ap3216c I2C registration failed %d\n", ret);
        return ret;
    }
    return ret;
}

static void __exit ap3216c_exit(void)
{
    i2c_del_driver(&ap3216c_driver);
}
module_init(ap3216c_init);
module_exit(ap3216c_exit);

/* 可使用module_i2c_driver结构体，等价与module_init和module_exit
   module_i2c_driver(ap3216c_driver);
  #define module_i2c_driver(__i2c_driver) \
	        module_driver(__i2c_driver, i2c_add_driver, i2c_del_driver)
*/
MODULE_LICENSE("GPL");
MODULE_AUTHOR("liyang.plus@foxmail.com");